
#[cfg(test)]
mod test {
    /* 
    // no-annotation -> Error 
    fn fname_no_anno() -> &String{
        let os = String::from("hello");
        &os
    }
    */
    fn fname<'a> (s: &'a String) -> &'a String {
        s
    }
    #[test]
    fn function(){
        let string ="string".to_string();
        let r = fname(&string);
        assert!(r.len() > 0);

        //let _ = fname_no_anno();
    }

    struct Struct <'a> {
        ref_s: &'a String,
    }
    impl <'a> Struct<'a> {
        fn s_fn(&self) -> &'a String {
            self.ref_s
        }
    }

    #[test]
    fn struct_test(){
        let string ="string".to_string();
        let s = Struct{ref_s: &string};
        let r = s.s_fn(); 
        assert!(r.len() > 0);
    }

/*
 *  Trait pattern function: 
 *  a function:  return struct 's ref 
 *      1. use structObject ref  with lifetime
 *      2. structObject's sub field ref 
 *
*/
    trait Trait {
        type Item;
        fn t_fn(&self) -> Self::Item;
    }

    //impl Trait 1. for Struct-with-lifetime
    impl <'a> Trait for Struct<'a> {
        type Item = &'a String;
        fn t_fn(&self) -> Self::Item {
            self.ref_s
        }
    }

    #[test]
    fn impl_trait_for_lefttime_struct(){
        let string = "string".to_string();
        let s = Struct{ ref_s:  &string};
        let r = s.t_fn();
        assert!(r.len() > 0);
    }

    struct StructObject {
        s: String, 
    }
    //impl Trait 2. for StructObject ref-self
    impl <'a> Trait for &'a StructObject {
        type Item = &'a String;
        fn t_fn(&self) -> Self::Item{
            &self.s
        }
    }


/* Compile Error 
 *  so this impl Trait is error!
    impl Trait for StructObject {
        type Item = & String;
        fn t_fn(&self) -> Self::Item {
            &self.s
        }
    }
*/
    #[test]
    fn impl_trait_for_struct_object() {
        let s = StructObject{ s: "string".to_string()};
        {
            let ref_s = &s;
            let r = ref_s.t_fn();
            assert!(r.len() > 0);
        }
    }
}
/*
//TODO: lifetime
    1. fn 
    fn fname<'a> (s: &'a String) -> &'a String{
        s
    }
    //Error: ->  ...
    fn fname(s: & string) -> & string{
        let os = String::from("hello");
        &os;
    }
    
    let s = "string"
    let r = fname(s); => {
        1: s = 'a s
        2: fname<'a>;
        3: r = 'a s;
    }

    2. struct 
    struct StructA <'a> {
        s: &'a String,
    }

    impl <'a> StructA <'a>{
        fn new(s: &'a String) -> StructA<'a> {
            StructA { s: s}
        }
    }

    let s = "string";
    let r = StructA::new(s); => {
        1. s = 'a s;
        2. StructA<'a>:new(s);
        3. StructA(r) <- 'a s;
    }
    
    3. trait 
        trait Trait {
            type Item;
            fn t_fn(&self) -> Item;
        }

    struct StructObject {
        s: String,
    }

    impl Trait for StructObject {
        Item = String;
        fn t_fn(&self) -> Self::Item{
            self.s
        }
    }
    let s = "string".to_string();
    let sa = StructObject{s};
    let r = sa.f_fn();

    struct StructA<'a> {
        s: &'a String,
    }
    impl <'a> Trait for StructA<'a> {
        Item = &'a String;
        fn t_fn(&self) -> Self::Item {
            self.s;
        }
    }

    let s = "string";
    let sa = StructA{s};
    let r = sa.t_fn();

    impl <'a> Trait for &'a StructObject {
        type Item = 'a String;
        fn t_fn(&self) -> Self::Item{
            &self.s
        }
    }

    let so = Struct{s:"hello".to_string()};
    {
        let ref_s = &s; -> start 
        let r = ref_s.t_fn();
    }
*/
